#[post("/library/clip_image_upload", data = "<data>")]
fn clip_image_upload(cookies: Cookies, data: Data) -> String {
    let user_info: UserInfo = get_cookies(&cookies);
    if user_info.id == 0 {
        return "fail:您未登录，请先登录".to_string();
    }

    let mut file_hostr: HoString = HoString::new();
    file_hostr.push_bytes(data.peek());
    let file_info: Vec<HoString> = file_hostr.split_bytes("\n".as_bytes());
    let file_name_op: Option<&HoString> = file_info.get(7);
    let mut file_name: HoString = HoString::new();
    if let Some(f) = file_name_op {
        let file_name_u8: &[u8] = f.trim();
        file_name.push_bytes(file_name_u8);
    } else {
        return "fail:Data数据不合法".to_string();
    }
    let file_name_array: Vec<HoString> = file_name.split_bytes(".".as_bytes());
    let file_name_array_len: usize = file_name_array.len() - 1;
    let file_extra_name: &HoString = file_name_array.get(file_name_array_len).unwrap();
    let now: SystemTime = SystemTime::now();
    let since_epoch_res = now.duration_since(UNIX_EPOCH);
    let since_epoch: Duration;
    if let Ok(d) = since_epoch_res {
        since_epoch = d;
    } else {
        return "fail:时间戳获取失败".to_string();
    }
    let timestamp = since_epoch.as_millis();
    let upload_name: String = format!("uploads/{}.{}", timestamp, file_extra_name.to_str());
    if let Ok(_) = data.stream_to_file(upload_name.as_str()) {
        let u8_vec: Vec<u8> = HoFile::read_file_u8vec(upload_name.as_str());
        let mut bytes: HoBytes = HoBytes::new();
        bytes.push_bytes(u8_vec.as_slice());
        let u8_vec_vec: Vec<Vec<u8>> = bytes.split_byte('\n' as u8);
        let mut content: HoBytes = HoBytes::new();
        for i in 24..u8_vec_vec.len() - 1 {
            match u8_vec_vec.get(i) {
                Some(v) => content.push_bytes(v.as_slice()),
                None => break
            }
        }
        HoFile::write_file_bytes(upload_name.as_str(), content.to_bytes());
        return format!("success:{}.{}", timestamp, file_extra_name.to_str());
    } else {
        return "fail:文件移动失败".to_string();
    }
}

#[post("/library/clip_video_upload", data = "<data>")]
fn clip_video_upload(cookies: Cookies, data: Data) -> String {
    let user_info: UserInfo = get_cookies(&cookies);
    if user_info.id == 0 {
        return "fail:您未登录，请先登录".to_string();
    }

    let mut file_hostr: HoString = HoString::new();
    file_hostr.push_bytes(data.peek());
    let file_info: Vec<HoString> = file_hostr.split_bytes("\n".as_bytes());
    let file_name_op: Option<&HoString> = file_info.get(7);
    let mut file_name: HoString = HoString::new();
    if let Some(f) = file_name_op {
        let file_name_u8: &[u8] = f.trim();
        file_name.push_bytes(file_name_u8);
    } else {
        return "fail:Data数据不合法".to_string();
    }
    let file_name_array: Vec<HoString> = file_name.split_bytes(".".as_bytes());
    let file_name_array_len: usize = file_name_array.len() - 1;
    let file_extra_name: &HoString = file_name_array.get(file_name_array_len).unwrap();
    let now: SystemTime = SystemTime::now();
    let since_epoch_res = now.duration_since(UNIX_EPOCH);
    let since_epoch: Duration;
    if let Ok(d) = since_epoch_res {
        since_epoch = d;
    } else {
        return "fail:时间戳获取失败".to_string();
    }
    let timestamp = since_epoch.as_millis();
    let upload_name: String = format!("uploads/{}.{}", timestamp, file_extra_name.to_str());
    if let Ok(_) = data.stream_to_file(upload_name.as_str()) {
        let u8_vec: Vec<u8> = HoFile::read_file_u8vec(upload_name.as_str());
        let mut bytes: HoBytes = HoBytes::new();
        bytes.push_bytes(u8_vec.as_slice());
        let u8_vec_vec: Vec<Vec<u8>> = bytes.split_byte('\n' as u8);
        let mut content: HoBytes = HoBytes::new();
        for i in 24..u8_vec_vec.len() - 1 {
            match u8_vec_vec.get(i) {
                Some(v) => content.push_bytes(v.as_slice()),
                None => break
            }
        }
        HoFile::write_file_bytes(upload_name.as_str(), content.to_bytes());
        return format!("success:{}.{}", timestamp, file_extra_name.to_str());
    } else {
        return "fail:文件移动失败".to_string();
    }
}

#[derive(FromForm)]
struct ClipUpload {
    id: usize,
    i_file_list: String,
    v_file_list: String
}

#[post("/library/upload_clip_order", data = "<form>")]
fn upload_clip_order(form: Form<ClipUpload>, state: State<MySqlDriver>) -> String {
    let i_file_list_hostr: HoString = HoString::copy_string(form.i_file_list.clone());
    let i_file_array: Vec<HoString> = i_file_list_hostr.split_str("|");
    let v_file_list_hostr: HoString = HoString::copy_string(form.v_file_list.clone());
    let v_file_array: Vec<HoString> = v_file_list_hostr.split_str("|");
    let mut i_file_string: String = String::new();
    let mut v_file_string: String = String::new();
    let mut i_file_len: u8 = 0;
    let mut v_file_len: u8 = 0;
    for i_file_item in &i_file_array {
        if i_file_item.length() == 0 {
            continue;
        }
        i_file_len += 1;
        if i_file_string.len() == 0 {
            i_file_string.push_str(i_file_item.to_str());
        } else {
            i_file_string.push_str(format!("|{}", i_file_item.to_str()).as_str());
        }
    }
    for v_file_item in &v_file_array {
        if v_file_item.length() == 0 {
            continue;
        }
        v_file_len += 1;
        if v_file_string.len() == 0 {
            v_file_string.push_str(v_file_item.to_str());
        } else {
            v_file_string.push_str(format!("|{}", v_file_item.to_str()).as_str());
        }
    }

    if i_file_len != 4 || v_file_len != 4 {
        return "fail:图片或视频数量不为4".to_string();
    }

    let mut i1920_1080_len: u8 = 0;
    let mut i1079_1440_len: u8 = 0;
    for i_file_item in i_file_array {
        if i_file_item.length() == 0 {
            continue;
        }
        let image_path_string: String = format!("uploads/{}", i_file_item.to_str());
        dbg!(image_path_string.clone());
        let path: &Path = Path::new(image_path_string.as_str());
        let img: DynamicImage = image::open(path).unwrap();
        let (width, height): (u32, u32) = img.dimensions();
        if width == 1920 && height == 1080 {
            i1920_1080_len += 1;
        } else if width == 1079 && height == 1440 {
            i1079_1440_len += 1;
        } else {
            return "fail:图片的尺寸不合规".to_string();
        }
    }
    if i1920_1080_len > 1 {
        return "fail:1920*1080的图片过多".to_string();
    }
    if i1079_1440_len > 3 {
        return "fail:1079*1440的图片过多".to_string();
    }

    let now: SystemTime = SystemTime::now();
    let since_epoch_res = now.duration_since(UNIX_EPOCH);
    let since_epoch: Duration;
    if let Ok(d) = since_epoch_res {
        since_epoch = d;
    } else {
        return "fail:时间戳获取失败".to_string();
    }
    let secs = since_epoch.as_secs();

    let pool_result: Result<Pool, mysql::Error> = Pool::new(state.driver.as_str());
    let pool: Pool;
    if let Ok(p) = pool_result {
        pool = p;
    } else {
        return "fail:无法建立数据库连接".to_string();
    }
    let conn_result: Result<PooledConn, mysql::Error> = pool.get_conn();
    let mut conn: PooledConn;
    if let Ok(c) = conn_result {
        conn = c;
    } else {
        return "fail:无法获取数据库连接".to_string();
    }

    let sql: String = format!("UPDATE `clip_order` SET `status` = 2, `i_file_list` = '{}', `v_file_list` = '{}', `update_datetime` = {} WHERE `id` = {}", i_file_string.as_str(), v_file_string.as_str(), secs, form.id);
    if let Err(_) = conn.exec_drop(sql.clone(), ()) {
        return "fail:订单提交失败".to_string();
    } else {
        return "success:".to_string();
    }
}

#[derive(FromForm)]
struct OrderMsg {
    id: usize,
    order_type: String,
    receive_id: usize,
    title: String,
    content: String
}

#[post("/library/upload_order_msg", data = "<form>")]
fn upload_order_msg(form: Form<OrderMsg>, cookies: Cookies, state: State<MySqlDriver>) -> String {
    let user_info: UserInfo = get_cookies(&cookies);
    let mut except_vec: Vec<char> = Vec::new();
    except_vec.push('\'');
    except_vec.push('"');
    except_vec.push('\\');
    let order_type_hostr: HoString = HoString::copy_string(form.order_type.clone());
    let title_hostr: HoString = HoString::copy_string(form.title.clone());
    let content_hostr: HoString = HoString::copy_string(form.content.clone());
    if order_type_hostr.length() == 0 || title_hostr.length() == 0 || content_hostr.length() == 0 {
        return "fail:表单不能有空".to_string();
    }
    if order_type_hostr.contains_char_vec(except_vec.clone(), 0) == true ||
        title_hostr.contains_char_vec(except_vec.clone(), 0) == true ||
        content_hostr.contains_char_vec(except_vec.clone(), 0) == true {
        return "fail:表单值不能包含引号和斜杠".to_string();
    }

    if order_type_hostr.compare_str("copywrite") == false && order_type_hostr.compare_str("clip") == false {
        return "fail:订单类型不合法".to_string();
    }

    let pool_result: Result<Pool, mysql::Error> = Pool::new(state.driver.as_str());
    let pool: Pool;
    if let Ok(p) = pool_result {
        pool = p;
    } else {
        return "fail:无法建立数据库连接".to_string();
    }
    let conn_result: Result<PooledConn, mysql::Error> = pool.get_conn();
    let mut conn: PooledConn;
    if let Ok(c) = conn_result {
        conn = c;
    } else {
        return "fail:无法获取数据库连接".to_string();
    }

    let mut sql: String = format!("SELECT `group_id` FROM `clip_order` WHERE `id` = {} LIMIT 1", form.id);
    let row: Row = conn.query_first(sql.clone()).unwrap().unwrap();
    let group_id: usize = from_row(row);
    if group_id == 0 {
        return "fail:未查询到小组".to_string();
    }

    let now: SystemTime = SystemTime::now();
    let since_epoch_res = now.duration_since(UNIX_EPOCH);
    let since_epoch: Duration;
    if let Ok(d) = since_epoch_res {
        since_epoch = d;
    } else {
        return "fail:时间戳获取失败".to_string();
    }
    let secs = since_epoch.as_secs();
    sql = format!("INSERT INTO `message`(`sender_id`, `copywrite_order_id`, `clip_order_id`, `receive_group_id`, `receive_user_id`, `title`, `content`, `create_datetime`) VALUES({}, {}, {}, {}, {}, '{}', '{}', {})", user_info.id, 0, form.id, group_id, form.receive_id, form.title, form.content, secs);
    if let Err(_) = conn.exec_drop(sql.clone(), ()) {
        return "fail:留言发表失败".to_string();
    } else {
        return "success:".to_string();
    }
}

#[get("/view_clip_order?<id>")]
fn view_clip_order(id: usize, cookies: Cookies, state: State<MySqlDriver>) -> Response<'static> {
    let mut res = Response::new();
    res.set_header(ContentType::HTML);
    let user_info: UserInfo = get_cookies(&cookies);

    // mod_id: String, 
    // mod_menu_open: String, 
    // sub_mod_id: String, 
    // page_title: String, 
    // title: String
    let header: String = get_header(
        "order-mod".to_string(), 
        "order-mod-menu-open".to_string(), 
        "clip-order-list".to_string(),
        "用户后台 - 剪辑订单".to_string(), 
        "剪辑订单".to_string(), &cookies,
        &state);

    let pool_result: Result<Pool, mysql::Error> = Pool::new(state.driver.as_str());
    let pool: Pool;
    if let Ok(p) = pool_result {
        pool = p;
    } else {
        res.set_sized_body(Cursor::new("无法建立数据库连接".to_string()));
        return res;
    }
    let conn_result: Result<PooledConn, mysql::Error> = pool.get_conn();
    let mut conn: PooledConn;
    if let Ok(c) = conn_result {
        conn = c;
    } else {
        res.set_sized_body(Cursor::new("无法获取数据库连接".to_string()));
        return res;
    }

    let mut sql: String = "SELECT `global_value` AS `clip_requirement` FROM `global_var` WHERE `global_key` = 'clip_requirement' LIMIT 1".to_string();
    let row_op: Option<Row> = conn.query_first(sql.clone()).unwrap();
    let row: Row;
    if let Some(r) = row_op {
        row = r;
    } else {
        res.set_sized_body(Cursor::new("无法获取剪辑要求".to_string()));
        return res;
    }
    let clip_requirement: String = from_row(row);

    sql = format!("SELECT `tg`.`id` AS `receive_id`, `copy_o`.`title`, `t`.`movie_name`, `copy_o`.`requirement`, `tg`.`type` AS `topic_type` FROM `clip_order` AS `clip_o` INNER JOIN `copywrite_order` AS `copy_o` ON `copy_o`.`id` = `clip_o`.`copywrite_id` INNER JOIN `topic` AS `t` ON `t`.`id` = `copy_o`.`topic_id` INNER JOIN `tag_group` AS `tg` ON `tg`.`id` = `copy_o`.`group_id` WHERE `clip_o`.`id` = {} LIMIT 1", id);
    let row_op: Option<Row> = conn.query_first(sql.clone()).unwrap();
    let row: Row;
    if let Some(r) = row_op {
        row = r;
    } else {
        res.set_sized_body(Cursor::new("无法获取订单信息".to_string()));
        return res;
    }
    let (receive_id, title, movie_name, requirement, topic_type): (usize, String, String, String, String) = from_row(row);

    sql = format!("SELECT `u`.`account` AS `msg_account`, `m`.`title` AS `msg_title`, `m`.`content` FROM `message` AS `m` INNER JOIN `user` AS `u` ON `u`.`id` = `m`.`sender_id` WHERE `m`.`clip_order_id` = {} AND (`m`.`sender_id` = {} OR `m`.`receive_user_id` = {})", id, user_info.id, user_info.id);
    let msg_vec: Vec<Row> = conn.query(sql.clone()).unwrap();
    let mut msg_html: String = String::new();
    for msg in msg_vec {
        let (msg_account, msg_title, content): (String, String, String) = from_row(msg);
        msg_html.push_str(format!("<div class=\"list-group-item list-group-item-action\">\
                            <div class=\"d-flex w-100 justify-content-between\">\
                                <h5 class=\"mb-1\">{}: {}</h5>\
                                <!-- <small><?= date('Y年m月d日 H:i:s', intval($v['create_datetime'])) ?></small> -->\
                            </div>\
                            <p class=\"mb-1\">{}</p>\
                          </div>", msg_account.as_str(), msg_title.as_str(), content.as_str()).as_str());
    }
    
    let mut src_vec: Vec<&[u8]> = Vec::new();
    let mut replace_vec: Vec<&[u8]> = Vec::new();

    let id_str: String = id.to_string();
    let receive_id_str: String = receive_id.to_string();
    let footer_string: String = get_footer();
    src_vec.push("{header}".as_bytes());
    src_vec.push("{id}".as_bytes());
    src_vec.push("{title}".as_bytes());
    src_vec.push("{requirement}".as_bytes());
    src_vec.push("{movie_name}".as_bytes());
    src_vec.push("{topic_type}".as_bytes());
    src_vec.push("{clip_requirement}".as_bytes());
    src_vec.push("{msg_html}".as_bytes());
    src_vec.push("{base_url}".as_bytes());
    src_vec.push("{receive_id}".as_bytes());
    src_vec.push("{footer}".as_bytes());
    replace_vec.push(header.as_bytes());
    replace_vec.push(id_str.as_bytes());
    replace_vec.push(title.as_bytes());
    replace_vec.push(requirement.as_bytes());
    replace_vec.push(movie_name.as_bytes());
    replace_vec.push(topic_type.as_bytes());
    replace_vec.push(clip_requirement.as_bytes());
    replace_vec.push(msg_html.as_bytes());
    replace_vec.push(state.base_url.as_bytes());
    replace_vec.push(receive_id_str.as_bytes());
    replace_vec.push(footer_string.as_bytes());

    let mut page_str: HoString = HoFile::read_file_bytes("web/view_clip_order.html");
    page_str = page_str.replace_bytes_vec(src_vec, replace_vec);
    let html: String = page_str.to_str().to_string().to_owned();
    res.set_sized_body(Cursor::new(html));
    return res;
}

